package cn.demoncat.util.zookeeper;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.imps.CuratorFrameworkState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.demoncat.util.zookeeper.constant.RetryType;


/**
 * Zookeeper 客户端连接池工厂
 * 
 * @author 延晓磊
 *
 * @since 2018年11月2日
 */
public class ZkPoolFactory implements PooledObjectFactory<CuratorFramework>{

	private static final Logger LOG = LoggerFactory.getLogger(ZkPoolFactory.class);
 
	//ZK连接地址
	private String connectString;
	//会话超时毫秒
	private int sessionTimeoutMs;
	//连接超时毫秒
	private int connectionTimeoutMs;
	//重试机制
	private final RetryPolicy retryType = RetryType.RUE;
	
	public ZkPoolFactory() {
		super();
	}
	
	public ZkPoolFactory(String connectString, int sessionTimeoutMs, int connectionTimeoutMs) {
		super();
		this.connectString = connectString;
		this.sessionTimeoutMs = sessionTimeoutMs;
		this.connectionTimeoutMs = connectionTimeoutMs;
	}

	/**
	 * 创建对象
	 * 
	 * @return
	 * @author 延晓磊
	 *
	 * @since 2018年11月2日
	 *
	 */
	@Override
	public PooledObject<CuratorFramework> makeObject() {
		// 使用工厂创建ZK客户端：ZK连接地址，会话超时，连接超时，重试机制
		CuratorFramework conn = CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryType);
		// 开始连接
		conn.start();
		LOG.info("开启Zookeeper连接：url = {}", connectString);
		// 返回池对象
		return new DefaultPooledObject<>(conn);
	}
	
	/**
	 * 销毁对象
	 * 
	 * @param p
	 * @author 延晓磊
	 *
	 * @since 2018年11月2日
	 *
	 */
	@Override
	public void destroyObject(PooledObject<CuratorFramework> p) {
		// 关闭连接
		CuratorFramework conn = p.getObject();
		if (conn != null) {
			conn.close();
		}
	}

	/**
	 * 校验对象
	 * 
	 * @param p
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年11月2日
	 *
	 */
	@Override
	public boolean validateObject(PooledObject<CuratorFramework> p) {
		// 检查连接
		CuratorFramework conn = p.getObject();
		if (conn != null) {
			return CuratorFrameworkState.STARTED.equals(conn.getState());
		}
		return false;
	}

	/**
	 * 激活对象
	 * 
	 * @param p
	 * @author 延晓磊
	 *
	 * @since 2018年11月2日
	 *
	 */
	@Override
	public void activateObject(PooledObject<CuratorFramework> p) {
		// pool.borrowObject() 获取时激活对象
	}

	/**
	 * 钝化对象
	 * 
	 * @param p
	 * @author 延晓磊
	 *
	 * @since 2018年11月2日
	 *
	 */
	@Override
	public void passivateObject(PooledObject<CuratorFramework> p) {
		// pool.returnObject(conn) 返回时钝化对象
	}

}
